package com.jackeysun.log

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Color
import android.util.AttributeSet
import android.util.Log
import android.util.SparseArray
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.jackeysun.log.databinding.ConsoleViewItemBinding
import com.jackeysun.log.databinding.ViewConsoleBinding
import java.io.File


/**
 *   Created by sunxunchao on 2021/12/13.
 */
class ConsoleView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {

    val adapter = Adapter()

    val COLORS = SparseArray<Int>()
    private var isTop = true
    private var isBottom = true

    private val mLogEntries = mutableListOf<LogEntry>()
    fun autoLog() {
        LogConfig.onLogcatListener = object : OnLogcatListener {
            override fun onLogcatInfo(log: String) {
                handLog(log)
            }
        }
    }

    fun setFile(file: File?) {
        file?.forEachLine {
            handLog(it)
        }
    }

    fun handLog(log:String){
        val list = log.split(Regex("\\s+"), limit = 7)
        if (list.size >= 7) {

            //12-14 10:39:17.474 30001 30025 D TAG     : onCreate: test
            val logEntry = LogEntry(
                list[0],
                list[1],
                list[2],
                list[3],
                list[4],
                list[5],
                list[6]
            )
            mLogEntries.add(logEntry)
            adapter.notifyItemInserted(mLogEntries.size - 1)
            if (isBottom) {
                mBinding.rv.scrollToPosition(mLogEntries.size - 1)
            }
        }
    }

    private var mBinding: ViewConsoleBinding

    init {
        val ta = getContext().obtainStyledAttributes(attrs, R.styleable.ConsoleView)

        val tag_v_color =
            ta.getColor(R.styleable.ConsoleView_color_verbose, Color.parseColor("#dfc0c0c0"))
        val tag_d_color =
            ta.getColor(R.styleable.ConsoleView_color_verbose, Color.parseColor("#dfffffff"))
        val tag_i_color =
            ta.getColor(R.styleable.ConsoleView_color_verbose, Color.parseColor("#ff64dd17"))
        val tag_w_color =
            ta.getColor(R.styleable.ConsoleView_color_verbose, Color.parseColor("#ff2962ff"))
        val tag_e_color =
            ta.getColor(R.styleable.ConsoleView_color_verbose, Color.parseColor("#ffd50000"))
        val tag_a_color =
            ta.getColor(R.styleable.ConsoleView_color_verbose, Color.parseColor("#ffff534e"))
        ta.recycle()
        COLORS.put(Log.VERBOSE, tag_v_color)
        COLORS.put(Log.DEBUG, tag_d_color)
        COLORS.put(Log.INFO, tag_i_color)
        COLORS.put(Log.WARN, tag_w_color)
        COLORS.put(Log.ERROR, tag_e_color)
        COLORS.put(Log.ASSERT, tag_a_color)

        adapter.colors = COLORS

        mBinding = ViewConsoleBinding.inflate(LayoutInflater.from(context), this, true)
        val manager = LinearLayoutManager(getContext())
        mBinding.rv.layoutManager = manager
        adapter.data = mLogEntries
        mBinding.rv.adapter = adapter
    }

    private val onScrollListener = object :
        RecyclerView.OnScrollListener() {
        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            super.onScrolled(recyclerView, dx, dy)
            isBottom = !mBinding.rv.canScrollVertically(1)
            isTop = !mBinding.rv.canScrollVertically(-1)
        }
    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        mBinding.rv.addOnScrollListener(onScrollListener)
    }


    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        mBinding.rv.removeOnScrollListener(onScrollListener)
    }
}


class Adapter :
    RecyclerView.Adapter<ViewHolder>() {

    lateinit var data: List<LogEntry>

    lateinit var colors: SparseArray<Int>

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
            ConsoleViewItemBinding.inflate(
                LayoutInflater.from(parent.context),
                parent,
                false
            )
        )
    }

    @SuppressLint("SetTextI18n")
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val logEntry = data[position]
        holder.itemBinding.tv.text = "${logEntry.time}\n${logEntry.level}/${logEntry.tag}"
        holder.itemBinding.logContent.text = "\n${logEntry.content}"

        when (logEntry.level.lowercase()) {
            "v" -> {
                holder.itemBinding.tv.setTextColor(colors.get(Log.VERBOSE))
                holder.itemBinding.logContent.setTextColor(colors.get(Log.VERBOSE))
            }
            "d" -> {
                holder.itemBinding.tv.setTextColor(colors.get(Log.DEBUG))
                holder.itemBinding.logContent.setTextColor(colors.get(Log.DEBUG))
            }
            "i" -> {
                holder.itemBinding.tv.setTextColor(colors.get(Log.INFO))
                holder.itemBinding.logContent.setTextColor(colors.get(Log.INFO))
            }
            "w" -> {
                holder.itemBinding.tv.setTextColor(colors.get(Log.WARN))
                holder.itemBinding.logContent.setTextColor(colors.get(Log.WARN))
            }
            "e" -> {
                holder.itemBinding.tv.setTextColor(colors.get(Log.ERROR))
                holder.itemBinding.logContent.setTextColor(colors.get(Log.ERROR))
            }
            "a" -> {
                holder.itemBinding.tv.setTextColor(colors.get(Log.ASSERT))
                holder.itemBinding.logContent.setTextColor(colors.get(Log.ASSERT))
            }
        }
    }

    override fun getItemCount(): Int = data.size
}

class ViewHolder(val itemBinding: ConsoleViewItemBinding) :
    RecyclerView.ViewHolder(itemBinding.root)